/**
 ******************************************************************************
 * @file    bl702_spi.c
 * @version V1.0
 * @date
 * @brief   This file is the standard driver c file
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; COPYRIGHT(c) 2020 Bouffalo Lab</center></h2>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of Bouffalo Lab nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 ******************************************************************************
 */

#include "bl702_spi.h"
#include "bl702_glb.h"

/** @addtogroup  BL702_Peripheral_Driver
 *  @{
 */

/** @addtogroup  SPI
 *  @{
 */

/** @defgroup  SPI_Private_Macros
 *  @{
 */
#define SPI_TX_TIMEOUT_COUNT (160 * 1000)
#define SPI_RX_TIMEOUT_COUNT (160 * 1000)

/*@} end of group SPI_Private_Macros */

/** @defgroup  SPI_Private_Types
 *  @{
 */

/*@} end of group SPI_Private_Types */

/** @defgroup  SPI_Private_Variables
 *  @{
 */
static const uint32_t    spiAddr[SPI_ID_MAX]                    = {SPI_BASE};
static intCallback_Type *spiIntCbfArra[SPI_ID_MAX][SPI_INT_ALL] = {{NULL}};

/*@} end of group SPI_Private_Variables */

/** @defgroup  SPI_Global_Variables
 *  @{
 */

/*@} end of group SPI_Global_Variables */

/** @defgroup  SPI_Private_Fun_Declaration
 *  @{
 */
#ifndef BFLB_USE_HAL_DRIVER
static void SPI_IntHandler(SPI_ID_Type spiNo);
#endif

/*@} end of group SPI_Private_Fun_Declaration */

/** @defgroup  SPI_Private_Functions
 *  @{
 */

/****************************************************************************/ /**
                                                                                * @brief  SPI interrupt common handler function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
#ifndef BFLB_USE_HAL_DRIVER
static void SPI_IntHandler(SPI_ID_Type spiNo) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  tmpVal = BL_RD_REG(SPIx, SPI_INT_STS);

  /* Transfer end interrupt,shared by both master and slave mode */
  if (BL_IS_REG_BIT_SET(tmpVal, SPI_END_INT) && !BL_IS_REG_BIT_SET(tmpVal, SPI_CR_SPI_END_MASK)) {
    BL_WR_REG(SPIx, SPI_INT_STS, BL_SET_REG_BIT(tmpVal, SPI_CR_SPI_END_CLR));

    if (spiIntCbfArra[spiNo][SPI_INT_END] != NULL) {
      spiIntCbfArra[spiNo][SPI_INT_END]();
    }
  }

  /* TX fifo ready interrupt(fifo count > fifo threshold) */
  if (BL_IS_REG_BIT_SET(tmpVal, SPI_TXF_INT) && !BL_IS_REG_BIT_SET(tmpVal, SPI_CR_SPI_TXF_MASK)) {
    if (spiIntCbfArra[spiNo][SPI_INT_TX_FIFO_REQ] != NULL) {
      spiIntCbfArra[spiNo][SPI_INT_TX_FIFO_REQ]();
    }
  }

  /*  RX fifo ready interrupt(fifo count > fifo threshold) */
  if (BL_IS_REG_BIT_SET(tmpVal, SPI_RXF_INT) && !BL_IS_REG_BIT_SET(tmpVal, SPI_CR_SPI_RXF_MASK)) {
    if (spiIntCbfArra[spiNo][SPI_INT_RX_FIFO_REQ] != NULL) {
      spiIntCbfArra[spiNo][SPI_INT_RX_FIFO_REQ]();
    }
  }

  /* Slave mode transfer time-out interrupt,triggered when bus is idle for the given value */
  if (BL_IS_REG_BIT_SET(tmpVal, SPI_STO_INT) && !BL_IS_REG_BIT_SET(tmpVal, SPI_CR_SPI_STO_MASK)) {
    BL_WR_REG(SPIx, SPI_INT_STS, BL_SET_REG_BIT(tmpVal, SPI_CR_SPI_STO_CLR));

    if (spiIntCbfArra[spiNo][SPI_INT_SLAVE_TIMEOUT] != NULL) {
      spiIntCbfArra[spiNo][SPI_INT_SLAVE_TIMEOUT]();
    }
  }

  /* Slave mode tx underrun error interrupt,trigged when tx is not ready during transfer */
  if (BL_IS_REG_BIT_SET(tmpVal, SPI_TXU_INT) && !BL_IS_REG_BIT_SET(tmpVal, SPI_CR_SPI_TXU_MASK)) {
    BL_WR_REG(SPIx, SPI_INT_STS, BL_SET_REG_BIT(tmpVal, SPI_CR_SPI_TXU_CLR));

    if (spiIntCbfArra[spiNo][SPI_INT_SLAVE_UNDERRUN] != NULL) {
      spiIntCbfArra[spiNo][SPI_INT_SLAVE_UNDERRUN]();
    }
  }

  /* TX/RX fifo overflow/underflow interrupt */
  if (BL_IS_REG_BIT_SET(tmpVal, SPI_FER_INT) && !BL_IS_REG_BIT_SET(tmpVal, SPI_CR_SPI_FER_MASK)) {
    if (spiIntCbfArra[spiNo][SPI_INT_FIFO_ERROR] != NULL) {
      spiIntCbfArra[spiNo][SPI_INT_FIFO_ERROR]();
    }
  }
}
#endif

/*@} end of group SPI_Private_Functions */

/** @defgroup  SPI_Public_Functions
 *  @{
 */

/****************************************************************************/ /**
                                                                                * @brief  SPI initialization function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  spiCfg: SPI configuration structure pointer
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Init(SPI_ID_Type spiNo, SPI_CFG_Type *spiCfg) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_WORK_MODE_TYPE(spiCfg->mod));
  CHECK_PARAM(IS_SPI_BYTE_INVERSE_TYPE(spiCfg->byteSequence));
  CHECK_PARAM(IS_SPI_BIT_INVERSE_TYPE(spiCfg->bitSequence));
  CHECK_PARAM(IS_SPI_CLK_PHASE_INVERSE_TYPE(spiCfg->clkPhaseInv));
  CHECK_PARAM(IS_SPI_CLK_POLARITY_TYPE(spiCfg->clkPolarity));

  /* Disable clock gate */
  GLB_AHB_Slave1_Clock_Gate(DISABLE, BL_AHB_SLAVE1_SPI);

  /* spi config */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_DEG_EN, spiCfg->deglitchEnable);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_M_CONT_EN, spiCfg->continuousEnable);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_BYTE_INV, spiCfg->byteSequence);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_BIT_INV, spiCfg->bitSequence);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_SCLK_PH, (spiCfg->clkPhaseInv + 1) & 1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_SCLK_POL, spiCfg->clkPolarity);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, spiCfg->frameSize);
  BL_WR_REG(SPIx, SPI_CONFIG, tmpVal);

#ifndef BFLB_USE_HAL_DRIVER
  Interrupt_Handler_Register(SPI_IRQn, SPI_IRQHandler);
#endif
  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI set default value of all registers function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_DeInit(SPI_ID_Type spiNo) {
  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  if (SPI_ID_0 == spiNo) {
    GLB_AHB_Slave1_Reset(BL_AHB_SLAVE1_SPI);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Length of data phase1/0,start/stop condition and interval between frame initialization
                                                                                *         function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  clockCfg: Clock configuration structure pointer
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_ClockConfig(SPI_ID_Type spiNo, SPI_ClockCfg_Type *clockCfg) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Configure length of data phase1/0 and start/stop condition */
  tmpVal = BL_RD_REG(SPIx, SPI_PRD_0);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_S, clockCfg->startLen - 1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_P, clockCfg->stopLen - 1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_D_PH_0, clockCfg->dataPhase0Len - 1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_D_PH_1, clockCfg->dataPhase1Len - 1);
  BL_WR_REG(SPIx, SPI_PRD_0, tmpVal);

  /* Configure length of interval between frame */
  tmpVal = BL_RD_REG(SPIx, SPI_PRD_1);
  BL_WR_REG(SPIx, SPI_PRD_1, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_I, clockCfg->intervalLen - 1));

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI configure fifo function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  fifoCfg: FIFO configuration structure pointer
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_FifoConfig(SPI_ID_Type spiNo, SPI_FifoCfg_Type *fifoCfg) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Set fifo threshold value */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_TX_FIFO_TH, fifoCfg->txFifoThreshold);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_RX_FIFO_TH, fifoCfg->rxFifoThreshold);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_1, tmpVal);

  /* Enable or disable dma function */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_DMA_TX_EN, fifoCfg->txFifoDmaEnable);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_DMA_RX_EN, fifoCfg->rxFifoDmaEnable);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Set SPI SCK Clcok
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  clk: Clk
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_SetClock(SPI_ID_Type spiNo, uint32_t clk) {
  uint32_t glb_div = 1, spi_div = 1;
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  if (clk > 36000000) {
    clk     = 36000000;
    glb_div = 1;
    spi_div = 1;
  } else if (clk > 140625) {
    glb_div = 1;
    spi_div = 36000000 / clk;
  } else if (clk > 70312) {
    glb_div = 2;
    spi_div = 18000000 / clk;
  } else if (clk > 35156) {
    glb_div = 4;
    spi_div = 9000000 / clk;
  } else if (clk > 4394) {
    glb_div = 32;
    spi_div = 1125000 / clk;
  } else {
    glb_div = 32;
    spi_div = 256;
  }

  /* Configure length of data phase1/0 and start/stop condition */
  tmpVal = BL_RD_REG(SPIx, SPI_PRD_0);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_S, spi_div - 1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_P, spi_div - 1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_D_PH_0, spi_div - 1);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_D_PH_1, spi_div - 1);
  BL_WR_REG(SPIx, SPI_PRD_0, tmpVal);

  tmpVal = BL_RD_REG(SPIx, SPI_PRD_1);
  BL_WR_REG(SPIx, SPI_PRD_1, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_PRD_I, spi_div - 1));

  GLB_Set_SPI_CLK(ENABLE, glb_div - 1);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Enable spi transfer
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  modeType: Master or slave mode select
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Enable(SPI_ID_Type spiNo, SPI_WORK_MODE_Type modeType) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_WORK_MODE_TYPE(modeType));

  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);

  if (modeType != SPI_WORK_MODE_SLAVE) {
    /* master mode */
    tmpVal = BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_S_EN);
    tmpVal = BL_SET_REG_BIT(tmpVal, SPI_CR_SPI_M_EN);
  } else {
    /* slave mode */
    tmpVal = BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_M_EN);
    tmpVal = BL_SET_REG_BIT(tmpVal, SPI_CR_SPI_S_EN);
  }

  BL_WR_REG(SPIx, SPI_CONFIG, tmpVal);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Disable spi transfer
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  modeType: Master or slave mode select
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Disable(SPI_ID_Type spiNo, SPI_WORK_MODE_Type modeType) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_WORK_MODE_TYPE(modeType));

  /* close master and slave */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  tmpVal = BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_M_EN);
  tmpVal = BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_S_EN);
  BL_WR_REG(SPIx, SPI_CONFIG, tmpVal);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Set time-out value to trigger interrupt when spi bus is idle for the given value
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  value: Time value
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_SetTimeOutValue(SPI_ID_Type spiNo, uint16_t value) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Set time-out value */
  tmpVal = BL_RD_REG(SPIx, SPI_STO_VALUE);
  BL_WR_REG(SPIx, SPI_STO_VALUE, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_STO_VALUE, value - 1));

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Set de-glitch function cycle count value
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  cnt: De-glitch function cycle count
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_SetDeglitchCount(SPI_ID_Type spiNo, uint8_t cnt) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Set count value */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  tmpVal = BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_DEG_CNT, cnt);
  BL_WR_REG(SPIx, SPI_CONFIG, tmpVal);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Enable rx data ignore function and set start/stop point
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  startPoint: Start point
                                                                                * @param  stopPoint: Stop point
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_RxIgnoreEnable(SPI_ID_Type spiNo, uint8_t startPoint, uint8_t stopPoint) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Enable rx ignore function */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Set start and stop point */
  tmpVal = startPoint << SPI_CR_SPI_RXD_IGNR_S_POS | stopPoint;
  BL_WR_REG(SPIx, SPI_RXD_IGNR, tmpVal);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Disable rx data ignore function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_RxIgnoreDisable(SPI_ID_Type spiNo) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Disable rx ignore function */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Clear tx fifo and tx fifo overflow/underflow status
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_ClrTxFifo(SPI_ID_Type spiNo) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Clear tx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR));

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Clear rx fifo and rx fifo overflow/underflow status
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_ClrRxFifo(SPI_ID_Type spiNo) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Clear rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR));

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Clear spi interrupt status
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  intType: SPI interrupt type
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_ClrIntStatus(SPI_ID_Type spiNo, SPI_INT_Type intType) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Clear certain or all interrupt */
  tmpVal = BL_RD_REG(SPIx, SPI_INT_STS);

  if (SPI_INT_ALL == intType) {
    tmpVal |= 0x1f << SPI_CR_SPI_END_CLR_POS;
  } else {
    tmpVal |= 1 << (intType + SPI_CR_SPI_END_CLR_POS);
  }

  BL_WR_REG(SPIx, SPI_INT_STS, tmpVal);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI mask or unmask certain or all interrupt
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  intType: SPI interrupt type
                                                                                * @param  intMask: SPI interrupt mask value( MASK:disbale interrupt,UNMASK:enable interrupt )
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_IntMask(SPI_ID_Type spiNo, SPI_INT_Type intType, BL_Mask_Type intMask) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_INT_TYPE(intType));
  CHECK_PARAM(IS_BL_MASK_TYPE(intMask));

  tmpVal = BL_RD_REG(SPIx, SPI_INT_STS);

  /* Mask or unmask certain or all interrupt */
  if (SPI_INT_ALL == intType) {
    if (MASK == intMask) {
      tmpVal |= 0x3f << SPI_CR_SPI_END_MASK_POS;
    } else {
      tmpVal &= ~(0x3f << SPI_CR_SPI_END_MASK_POS);
    }
  } else {
    if (MASK == intMask) {
      tmpVal |= 1 << (intType + SPI_CR_SPI_END_MASK_POS);
    } else {
      tmpVal &= ~(1 << (intType + SPI_CR_SPI_END_MASK_POS));
    }
  }

  /* Write back */
  BL_WR_REG(SPIx, SPI_INT_STS, tmpVal);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  Install spi interrupt callback function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  intType: SPI interrupt type
                                                                                * @param  cbFun: Pointer to interrupt callback function. The type should be void (*fn)(void)
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Int_Callback_Install(SPI_ID_Type spiNo, SPI_INT_Type intType, intCallback_Type *cbFun) {
  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_INT_TYPE(intType));

  spiIntCbfArra[spiNo][intType] = cbFun;

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI write data to tx fifo
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  data: Data to write
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_SendData(SPI_ID_Type spiNo, uint32_t data) {
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Write tx fifo */
  BL_WR_REG(SPIx, SPI_FIFO_WDATA, data);

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI send 8-bit datas
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  buff: Buffer of datas
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Send_8bits(SPI_ID_Type spiNo, uint8_t *buff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t txLen = 0;
  uint32_t rData;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_TX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 0));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (txLen = 0; txLen < tmpVal; txLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, (uint32_t)buff[txLen]);
  }

  /* Wait receive data and send the rest of the data */
  for (; txLen < length; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    rData |= BL_RD_REG(SPIx, SPI_FIFO_RDATA);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, (uint32_t)buff[txLen]);
  }

  /* Wait receive the rest of the data */
  for (txLen = 0; txLen < tmpVal; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    rData |= BL_RD_REG(SPIx, SPI_FIFO_RDATA);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI send 16-bit datas
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  buff: Buffer of datas
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Send_16bits(SPI_ID_Type spiNo, uint16_t *buff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t txLen = 0;
  uint32_t rData;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_TX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 1));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (txLen = 0; txLen < tmpVal; txLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, (uint32_t)buff[txLen]);
  }

  /* Wait receive data and send the rest of the data */
  for (; txLen < length; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    rData |= BL_RD_REG(SPIx, SPI_FIFO_RDATA);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, (uint32_t)buff[txLen]);
  }

  /* Wait receive the rest of the data */
  for (txLen = 0; txLen < tmpVal; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    rData |= BL_RD_REG(SPIx, SPI_FIFO_RDATA);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI send 24-bit datas
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  buff: Buffer of datas
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Send_24bits(SPI_ID_Type spiNo, uint32_t *buff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t txLen = 0;
  uint32_t rData;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_TX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 2));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (txLen = 0; txLen < tmpVal; txLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, buff[txLen]);
  }

  /* Wait receive data and send the rest of the data */
  for (; txLen < length; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    rData |= BL_RD_REG(SPIx, SPI_FIFO_RDATA);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, buff[txLen]);
  }

  /* Wait receive the rest of the data */
  for (txLen = 0; txLen < tmpVal; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    rData |= BL_RD_REG(SPIx, SPI_FIFO_RDATA);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI send 32-bit datas
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  buff: Buffer of datas
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Send_32bits(SPI_ID_Type spiNo, uint32_t *buff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t txLen = 0;
  uint32_t rData;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_TX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 3));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (txLen = 0; txLen < tmpVal; txLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, buff[txLen]);
  }

  /* Wait receive data and send the rest of the data */
  for (; txLen < length; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    rData |= BL_RD_REG(SPIx, SPI_FIFO_RDATA);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, buff[txLen]);
  }

  /* Wait receive the rest of the data */
  for (txLen = 0; txLen < tmpVal; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    rData |= BL_RD_REG(SPIx, SPI_FIFO_RDATA);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI receive 8-bit datas
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  buff: Buffer of datas
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Recv_8bits(SPI_ID_Type spiNo, uint8_t *buff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t rxLen      = 0;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_RX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 0));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo with 0 */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (rxLen = 0; rxLen < tmpVal; rxLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, 0);
  }

  /* Wait receive data and send the rest of the data 0 */
  for (rxLen = 0; rxLen < length - tmpVal; rxLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    buff[rxLen] = (uint8_t)(BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xff);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, 0);
  }

  /* Wait receive the rest of the data */
  for (; rxLen < length; rxLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    buff[rxLen] = (uint8_t)(BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xff);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI receive 16-bit datas
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  buff: Buffer of datas
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Recv_16bits(SPI_ID_Type spiNo, uint16_t *buff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t rxLen      = 0;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_RX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 1));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo with 0 */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (rxLen = 0; rxLen < tmpVal; rxLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, 0);
  }

  /* Wait receive data and send the rest of the data 0 */
  for (rxLen = 0; rxLen < length - tmpVal; rxLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    buff[rxLen++] = (uint16_t)(BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xffff);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, 0);
  }

  /* Wait receive the rest of the data */
  for (; rxLen < length; rxLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    buff[rxLen++] = (uint16_t)(BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xffff);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI receive 24-bit datas
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  buff: Buffer of datas
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Recv_24bits(SPI_ID_Type spiNo, uint32_t *buff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t rxLen      = 0;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_RX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 2));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo with 0 */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (rxLen = 0; rxLen < tmpVal; rxLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, 0);
  }

  /* Wait receive data and send the rest of the data 0 */
  for (rxLen = 0; rxLen < length - tmpVal; rxLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    buff[rxLen++] = BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xffffff;
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, 0);
  }

  /* Wait receive the rest of the data */
  for (; rxLen < length; rxLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    buff[rxLen++] = BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xffffff;
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI receive 32-bit datas
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  buff: Buffer of datas
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_Recv_32bits(SPI_ID_Type spiNo, uint32_t *buff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t rxLen      = 0;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_RX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 3));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo with 0 */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (rxLen = 0; rxLen < tmpVal; rxLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, 0);
  }

  /* Wait receive data and send the rest of the data 0 */
  for (rxLen = 0; rxLen < length - tmpVal; rxLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    buff[rxLen++] = BL_RD_REG(SPIx, SPI_FIFO_RDATA);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, 0);
  }

  /* Wait receive the rest of the data */
  for (; rxLen < length; rxLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    buff[rxLen++] = BL_RD_REG(SPIx, SPI_FIFO_RDATA);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI send and receive 8-bit datas at the same time
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  sendBuff: Buffer of datas to send
                                                                                * @param  recvBuff: Buffer of datas received
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_SendRecv_8bits(SPI_ID_Type spiNo, uint8_t *sendBuff, uint8_t *recvBuff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t txLen      = 0;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_RX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 0));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (txLen = 0; txLen < tmpVal; txLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, (uint32_t)sendBuff[txLen]);
  }

  /* Wait receive data and send the rest of the data */
  for (; txLen < length; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    recvBuff[txLen - tmpVal] = (uint8_t)(BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xff);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, (uint32_t)sendBuff[txLen]);
  }

  /* Wait receive the rest of the data */
  for (txLen = 0; txLen < tmpVal; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    recvBuff[length - tmpVal + txLen] = (uint8_t)(BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xff);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI send and receive 16-bit datas at the same time
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  sendBuff: Buffer of datas to send
                                                                                * @param  recvBuff: Buffer of datas received
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_SendRecv_16bits(SPI_ID_Type spiNo, uint16_t *sendBuff, uint16_t *recvBuff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t txLen      = 0;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_RX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 1));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (txLen = 0; txLen < tmpVal; txLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, (uint32_t)sendBuff[txLen]);
  }

  /* Wait receive data and send the rest of the data */
  for (; txLen < length; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    recvBuff[txLen - tmpVal] = (uint16_t)(BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xffff);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, (uint32_t)sendBuff[txLen]);
  }

  /* Wait receive the rest of the data */
  for (txLen = 0; txLen < tmpVal; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    recvBuff[length - tmpVal + txLen] = (uint16_t)(BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xffff);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI send and receive 24-bit datas at the same time
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  sendBuff: Buffer of datas to send
                                                                                * @param  recvBuff: Buffer of datas received
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_SendRecv_24bits(SPI_ID_Type spiNo, uint32_t *sendBuff, uint32_t *recvBuff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t txLen      = 0;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_RX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 2));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (txLen = 0; txLen < tmpVal; txLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, sendBuff[txLen]);
  }

  /* Wait receive data and send the rest of the data */
  for (; txLen < length; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    recvBuff[txLen - tmpVal] = BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xffffff;
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, sendBuff[txLen]);
  }

  /* Wait receive the rest of the data */
  for (txLen = 0; txLen < tmpVal; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    recvBuff[length - tmpVal + txLen] = BL_RD_REG(SPIx, SPI_FIFO_RDATA) & 0xffffff;
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI send and receive 32-bit datas at the same time
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  sendBuff: Buffer of datas to send
                                                                                * @param  recvBuff: Buffer of datas received
                                                                                * @param  length: Length of buffer
                                                                                * @param  timeoutType: Enable or disable timeout judgment
                                                                                *
                                                                                * @return SUCCESS
                                                                                *
                                                                                *******************************************************************************/
BL_Err_Type SPI_SendRecv_32bits(SPI_ID_Type spiNo, uint32_t *sendBuff, uint32_t *recvBuff, uint32_t length, SPI_Timeout_Type timeoutType) {
  uint32_t tmpVal;
  uint32_t txLen      = 0;
  uint32_t SPIx       = spiAddr[spiNo];
  uint32_t timeoutCnt = SPI_RX_TIMEOUT_COUNT;

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_TIMEOUT_TYPE(timeoutType));

  /* Set valid width for each fifo entry */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_SET_REG_BITS_VAL(tmpVal, SPI_CR_SPI_FRAME_SIZE, 3));

  /* Disable rx ignore */
  tmpVal = BL_RD_REG(SPIx, SPI_CONFIG);
  BL_WR_REG(SPIx, SPI_CONFIG, BL_CLR_REG_BIT(tmpVal, SPI_CR_SPI_RXD_IGNR_EN));

  /* Clear tx and rx fifo */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_TX_FIFO_CLR);
  tmpVal = BL_SET_REG_BIT(tmpVal, SPI_RX_FIFO_CLR);
  BL_WR_REG(SPIx, SPI_FIFO_CONFIG_0, tmpVal);

  /* Fill tx fifo */
  tmpVal = length <= (SPI_TX_FIFO_SIZE) ? length : SPI_TX_FIFO_SIZE;

  for (txLen = 0; txLen < tmpVal; txLen++) {
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, sendBuff[txLen]);
  }

  /* Wait receive data and send the rest of the data */
  for (; txLen < length; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    recvBuff[txLen - tmpVal] = BL_RD_REG(SPIx, SPI_FIFO_RDATA);
    BL_WR_REG(SPIx, SPI_FIFO_WDATA, sendBuff[txLen]);
  }

  /* Wait receive the rest of the data */
  for (txLen = 0; txLen < tmpVal; txLen++) {
    timeoutCnt = SPI_RX_TIMEOUT_COUNT;

    while (SPI_GetRxFifoCount(spiNo) == 0) {
      if (timeoutType) {
        timeoutCnt--;

        if (timeoutCnt == 0) {
          return TIMEOUT;
        }
      }
    }

    recvBuff[length - tmpVal + txLen] = BL_RD_REG(SPIx, SPI_FIFO_RDATA);
  }

  return SUCCESS;
}

/****************************************************************************/ /**
                                                                                * @brief  SPI read data from rx fifo
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return Data readed
                                                                                *
                                                                                *******************************************************************************/
uint32_t SPI_ReceiveData(SPI_ID_Type spiNo) {
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  return BL_RD_REG(SPIx, SPI_FIFO_RDATA);
}

/****************************************************************************/ /**
                                                                                * @brief  Get tx fifo available count value function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return Count value
                                                                                *
                                                                                *******************************************************************************/
uint8_t SPI_GetTxFifoCount(SPI_ID_Type spiNo) {
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Get count value */
  return BL_GET_REG_BITS_VAL(BL_RD_REG(SPIx, SPI_FIFO_CONFIG_1), SPI_TX_FIFO_CNT);
}

/****************************************************************************/ /**
                                                                                * @brief  Get rx fifo available count value function
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return Count value
                                                                                *
                                                                                *******************************************************************************/
uint8_t SPI_GetRxFifoCount(SPI_ID_Type spiNo) {
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Get count value */
  return BL_GET_REG_BITS_VAL(BL_RD_REG(SPIx, SPI_FIFO_CONFIG_1), SPI_RX_FIFO_CNT);
}

/****************************************************************************/ /**
                                                                                * @brief  Get spi interrupt status
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  intType: SPI interrupt type
                                                                                *
                                                                                * @return Status of interrupt
                                                                                *
                                                                                *******************************************************************************/
BL_Sts_Type SPI_GetIntStatus(SPI_ID_Type spiNo, SPI_INT_Type intType) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_INT_TYPE(intType));

  /* Get certain or all interrupt status */
  tmpVal = BL_RD_REG(SPIx, SPI_INT_STS);

  if (SPI_INT_ALL == intType) {
    if ((tmpVal & 0x3f) != 0) {
      return SET;
    } else {
      return RESET;
    }
  } else {
    if ((tmpVal & (1U << intType)) != 0) {
      return SET;
    } else {
      return RESET;
    }
  }
}

/****************************************************************************/ /**
                                                                                * @brief  Get indicator of spi bus busy
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                *
                                                                                * @return Status of spi bus
                                                                                *
                                                                                *******************************************************************************/
BL_Sts_Type SPI_GetBusyStatus(SPI_ID_Type spiNo) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));

  /* Get bus busy status */
  tmpVal = BL_RD_REG(SPIx, SPI_BUS_BUSY);

  if (BL_IS_REG_BIT_SET(tmpVal, SPI_STS_SPI_BUS_BUSY)) {
    return SET;
  } else {
    return RESET;
  }
}

/****************************************************************************/ /**
                                                                                * @brief  Get tx/rx fifo overflow or underflow status
                                                                                *
                                                                                * @param  spiNo: SPI ID type
                                                                                * @param  fifoSts: Select tx/rx overflow or underflow
                                                                                *
                                                                                * @return Status of tx/rx fifo
                                                                                *
                                                                                *******************************************************************************/
BL_Sts_Type SPI_GetFifoStatus(SPI_ID_Type spiNo, SPI_FifoStatus_Type fifoSts) {
  uint32_t tmpVal;
  uint32_t SPIx = spiAddr[spiNo];

  /* Check the parameters */
  CHECK_PARAM(IS_SPI_ID_TYPE(spiNo));
  CHECK_PARAM(IS_SPI_FIFOSTATUS_TYPE(fifoSts));

  /* Get tx/rx fifo overflow or underflow status */
  tmpVal = BL_RD_REG(SPIx, SPI_FIFO_CONFIG_0);

  if ((tmpVal & (1U << (fifoSts + SPI_TX_FIFO_OVERFLOW_POS))) != 0) {
    return SET;
  } else {
    return RESET;
  }
}

/****************************************************************************/ /**
                                                                                * @brief  SPI interrupt handler
                                                                                *
                                                                                * @param  None
                                                                                *
                                                                                * @return None
                                                                                *
                                                                                *******************************************************************************/
#ifndef BFLB_USE_HAL_DRIVER
void SPI_IRQHandler(void) { SPI_IntHandler(SPI_ID_0); }
#endif

/*@} end of group SPI_Public_Functions */

/*@} end of group SPI */

/*@} end of group BL702_Peripheral_Driver */
